package face.pay.open.material.service.impl;

import com.face.pay.IPayConfigServer;
import com.face.pay.SecurityConfig;
import com.face.pay.WxApiConfig;
import com.github.wxpay.sdk.WXPayConstants;
import com.github.wxpay.sdk.WXPayRequest;
import com.github.wxpay.sdk.WXPayUtil;
import face.pay.dao.MchApplymentUpgradeInfoDao;
import face.pay.dao.OemConfigInfoDao;
import face.pay.dao.OemInfoDao;
import face.pay.entity.MchApplymentUpgradeInfo;
import face.pay.open.material.service.IMchApplymentUpgradeService;
import face.pay.open.server.CertInfo;
import face.pay.open.server.CertficatesServer;
import face.pay.open.util.request.ApiRequestParam;
import face.pay.open.util.request.ErrorCode;
import face.pay.open.validate.ApiParamValidate;
import face.pay.util.RSAEncryp;
import face.pay.util.ResultMessage;
import face.pay.util.bean.JavaBeanUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.UUID;

/**
 * @Auther:
 * @Date:
 * @Description:
 */
@Service
@Slf4j
public class MchApplymentUpgradeServiceimpl implements IMchApplymentUpgradeService {


    private static final String domain = "api.mch.weixin.qq.com";


    @Autowired
    private ApiParamValidate apiParamValidate;

    @Autowired
    private OemConfigInfoDao oemConfigInfoDao;

    @Autowired
    private OemInfoDao oemInfoDao;

    @Autowired
    private IPayConfigServer wxApiConfigServer;


    @Autowired
    private CertficatesServer certficatesServer;

    @Autowired
    private MchApplymentUpgradeInfoDao mchApplymentUpgradeInfoDao;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResultMessage applyment(String json) {

        log.info("商户进件：报文" + json);

        Integer code = ErrorCode.ERROR;

        String message = "未知错误";


        ApiRequestParam apiRequestParam = apiParamValidate.parse(json);


        try {
            if (apiRequestParam != null) {

                Integer oemId = apiRequestParam.getOemId();

                log.info("oemId:" + oemId);
                WxApiConfig config = wxApiConfigServer.getConfig(oemId);

                if (config == null) {
                    code = ErrorCode.ERROR;
                    message = "平台配置信息不全";
                } else {

                    SecurityConfig securityConfig = config.getSecurityConfig();
                    /**
                     * 签名验证
                     * 参数验证
                     *
                     */

                    /**
                     * 商户进件的资料信息
                     */
                    Map<String, String> data = apiRequestParam.getData();

                    Boolean validate = apiParamValidate.validate(data, apiRequestParam.getSign(), securityConfig);

                    if (validate) {

                        MchApplymentUpgradeInfo mchApplymentInfo = (MchApplymentUpgradeInfo) JavaBeanUtils.mapToBean(data, MchApplymentUpgradeInfo.class);


                        Map<String, String> map = JavaBeanUtils.toMap(mchApplymentInfo);


                        CertInfo certInfo = this.certficatesServer.getcertficatesInfo(config);

                        String cert_sn = certInfo.getSerial_no();


                        if (StringUtils.isNotBlank(cert_sn)) {

                            map.put("version", "1.0");

                            map.put("cert_sn", cert_sn);

                            map.put("mch_id", config.getMchID());
                            map.put("sign_type", "HMAC-SHA256");

                            String nonce_str = WXPayUtil.generateNonceStr();

                            map.put("nonce_str", nonce_str);
                            String business_time = mchApplymentInfo.getBusiness_time();

                            String[] times = business_time.split("[|]");
                            business_time = "[\"" + times[0] + "\"" + ",\"" + times[1] + "\"]";


                            map.put("business_time", business_time);


                            log.info("敏感字段加密");
                            /**
                             * 指定需要加密处理的字段
                             */
                            List keyList = new ArrayList();
                            keyList.add("legal_person");


                            String cer_public_key = RSAEncryp.decryptCertSN(certInfo.getAssociated_data(), certInfo.getNonce(), certInfo.getCipherText(), certInfo.getApi3key());

                            RSAEncryp.rsaEncryptByCert(map, keyList, cer_public_key);
                            /**
                             * 敏感字段加密
                             */
                            log.info("敏感字段加密结束");


                            String xml = WXPayUtil.generateSignedXml(map, config.getKey(), WXPayConstants.SignType.HMACSHA256);
                            log.info("调用微信进件接口:" + xml);
                            WXPayRequest wxPayRequest = new WXPayRequest(config);

                            String urlSuffix = "/applyment/micro/submitupgrade";

                            String result = wxPayRequest.requestOnce(domain, urlSuffix, UUID.randomUUID().toString(), xml, 8000, 6000, true);

                            log.info("微信进件接口返回结果:" + result);
                            Map<String, String> resultMap = WXPayUtil.xmlToMap(result);


                            Boolean isOk = WXPayUtil.isSuccess(resultMap);

                            if (isOk) {


                                mchApplymentInfo.setOemId(oemId);
                                mchApplymentInfo.setApplyment_state("CHECKING");
                                mchApplymentInfo.setApplyment_state_desc("资料校验中");
                                this.mchApplymentUpgradeInfoDao.insert(mchApplymentInfo);


                                return ResultMessage.createSuccess("提交资料成功");

                            } else {
                                code = ErrorCode.WX_SEND_ERROR;
                                message = resultMap.get("return_msg");
                                message += resultMap.get("err_code_des");

                            }


                        } else {
                            code = ErrorCode.ERROR;
                            message = "获取证书序列出错";
                        }
                    } else {
                        code = ErrorCode.SING_ERROR;
                        message = ErrorCode.SING_ERROR_MESSAGE;
                    }
                }
            }
        } catch (Exception e) {
            log.error("进件异常", e);
            code = ErrorCode.ERROR;
        }


        return ResultMessage.createFail(message).setErrorCode(code);
    }
}
